package com.gonsin.gview.annotations.service;

import com.gonsin.gview.annotations.GViewScan;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.env.Environment;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.filter.TypeFilter;
import org.springframework.util.ClassUtils;

import java.util.*;
import java.util.stream.Stream;

public class GViewApplication implements ImportBeanDefinitionRegistrar , EnvironmentAware, ResourceLoaderAware {

    /**
     * 扫描的包名
     */
    private static final Set<String> scanPackage = new HashSet<>();

    /**
     * 排除的包名
     */
    private static final Set<String> excludePackage = new HashSet<>();

    public static String[] getScanPackage() {
        return scanPackage.toArray(new String[0]);
    }

    private Environment environment;
    private ResourceLoader resourceLoader;

    private final Map<TypeFilter, ImportBeanDefinitionRegistrar> senderRegistrars = new HashMap<TypeFilter, ImportBeanDefinitionRegistrar>();

    @SneakyThrows
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        Class<?> clazz = ClassUtils.forName(importingClassMetadata.getClassName(), ClassUtils.getDefaultClassLoader());
//        Optional.ofNullable(clazz.getAnnotation(SpringBootApplication.class)).ifPresent(it -> primarySource = clazz);
        GViewScan eruptScan = clazz.getAnnotation(GViewScan.class);
        if (eruptScan.value().length == 0) {
            scanPackage.add(clazz.getPackage().getName());
        } else {
            //                    .filter(pack -> !pack.equals("com.gonsin"))
            scanPackage.addAll(Arrays.asList(eruptScan.value()));
        }

        if(eruptScan.excludePackageName().length > 0){
            excludePackage.addAll(Arrays.asList(eruptScan.excludePackageName()));
        }


//        Collection<String> basePackages = Arrays.asList(GViewApplication.getScanPackage());
//
//        ClassPathScanningCandidateComponentProvider scanner =
//                new ClassPathScanningCandidateComponentProvider(false, this.environment) {
//
//                    @Override
//                    protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
//                        return beanDefinition.getMetadata().isIndependent()
//                                && !beanDefinition.getMetadata().isAnnotation();
//                    }
//
//                };
//
//        for (TypeFilter typeFilter : this.senderRegistrars.keySet()) {
//            scanner.addIncludeFilter(typeFilter);
//        }
//
//        scanner.setResourceLoader(this.resourceLoader);
//
//        for (String basePackage : basePackages) {
//            Set<BeanDefinition> candidateComponents = scanner.findCandidateComponents(basePackage);
//            for (BeanDefinition candidateComponent : candidateComponents) {
//                if (candidateComponent instanceof AnnotatedBeanDefinition) {
//                    for (ImportBeanDefinitionRegistrar registrar : this.senderRegistrars.values()) {
//                        registrar.registerBeanDefinitions(((AnnotatedBeanDefinition) candidateComponent).getMetadata(),
//                                registry);
//                    }
//                }
//            }
//        }
    }

    @Override
    public void setEnvironment(Environment environment) {
        this.environment = environment;
    }

    @Override
    public void setResourceLoader(ResourceLoader resourceLoader) {
        this.resourceLoader = resourceLoader;
    }
}
